package fun.diaoer.mapper.interceptor;

import java.beans.PropertyDescriptor;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.springframework.util.IdGenerator;

import fun.diaoer.common.BeanUtil;
import fun.diaoer.common.Contants;
import fun.diaoer.common.DateUtil;
import fun.diaoer.common.SpringContextsUtil;
import fun.diaoer.common.StringUtil;
import fun.diaoer.entity.BaseEntity;
import fun.diaoer.mapper.base.DIBaseMapper;
import fun.diaoer.service.AbstractService;
import lombok.extern.slf4j.Slf4j;

/**
 * 给默认字段赋值，创建人、创建时间、更新人、更新时间等
 *
 */

@Slf4j
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class InsertAndUpdateInterceptor extends AbstractService implements Interceptor {

	@SuppressWarnings("rawtypes")
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		Object[] args = invocation.getArgs();

		if (args == null || args.length < 2)
			return invocation.proceed();

		// 第一个参数
		boolean isInsert = true;
		if (args[0] instanceof MappedStatement) {
			MappedStatement ms = (MappedStatement) args[0];
			SqlCommandType sqlCommandType = ms.getSqlCommandType();
			// 如果是“增加”或“更新”操作，则继续进行默认操作信息赋值。否则，则退出
			if (sqlCommandType == SqlCommandType.INSERT)
				isInsert = true;
			else if (sqlCommandType == SqlCommandType.UPDATE)
				isInsert = false;
			else
				return invocation.proceed();
		} else
			return invocation.proceed();

		// 第二个参数处理
		if (args[1] instanceof Map) {
			Map map = (Map) args[1];
			for (Object obj : map.values()) {
				if (obj instanceof BaseEntity) {
					setBaseEntityValue((BaseEntity) obj, isInsert);
				}
			}
		} else if (args[1] instanceof BaseEntity) {
			setBaseEntityValue((BaseEntity) args[1], isInsert);
		}

		return invocation.proceed();
	}

	public void setBaseEntityValue(BaseEntity baseModel, boolean isInsert) {
		Date startTime = new Date();

		// 随便获取一个DIBaseMapper
		String[] mappers = SpringContextsUtil.getApplicationContext().getBeanNamesForType(DIBaseMapper.class);
		if (mappers == null || mappers.length <= 0)
			return;

		// 通过反射赋值UUID
		if (isInsert) {
			try {
				String uuidName = BeanUtil.getEntityUuidProperty(baseModel);
				PropertyDescriptor propertyDescriptor = BeanUtil.getPropertyDescriptor(baseModel.getClass(), uuidName);
				if (StringUtil.isBlank((String) propertyDescriptor.getReadMethod().invoke(baseModel)))
					propertyDescriptor.getWriteMethod().invoke(baseModel, Contants.getGuid());
			} catch (Exception e) {
				log.error(e.toString(), e);
			}
		}

		DIBaseMapper <?> baseMapper = (DIBaseMapper<?>) SpringContextsUtil.getBean(mappers[0]);
		Timestamp now = baseMapper.getDatabaseTimestamp();
		String userId = getUserId();
		if (isInsert) {
			baseModel.setCreateDt(now);
			// 当前用户为系统用户时，允许传入值作为创建人
			if (StringUtil.isBlank(baseModel.getCreateBy()) || !StringUtil.equals(userId, Contants.SYS_USER_ID))
				baseModel.setCreateBy(userId);
			// 新增时允许传入版本号字段作为初始版本号
			if (baseModel.getRecVer() == null)
				baseModel.setRecVer(0);
		}
		baseModel.setUpdateDt(now);
		baseModel.setUpdateBy(userId);

		log.debug("DefaultValueInterceptor cost: {}", DateUtil.differentDays(startTime, new Date()));
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
	}

}
